/*
 * SWTIMERC1.c
 *
 *  Created on: 17/11/2012
 *      Author: Richard
 */

//#include <msp430.h>
#include "SWTIMERC1.h"
#include "../UI/BUTTON/BTNC1.h"
#include "../../sensor.h"
#include "../../Driver/HWTIMER/HWTIMERC1.h"
#include "../../Driver/DIO/DIOC1.h"


static SWTIM_tstTimer *SWTIM__stTimerHead;

static void SWTIM__vUpdateTimer( void );
static void SWTIM__vPlaceTimer( SWTIM_tstTimer *timer );

static void SWTIM__vUpdateTimer( void )
{
   uint16 u16Elapsed;

   ENTER_CRITICAL();
   u16Elapsed = SWTIM_nGetTimerVal * SWTIM_nTimerInterval;
   SWTIM_nClearTimerVal;
   EXIT_CRITICAL();

   while( ( SWTIM__stTimerHead != NULL ) && ( SWTIM__stTimerHead->timeout <= u16Elapsed ) )
   {
      SWTIM_tstTimer *timer = SWTIM__stTimerHead;

      u16Elapsed -= SWTIM__stTimerHead->timeout;
      SWTIM__stTimerHead = SWTIM__stTimerHead->next;

      if( timer->mode == SWTIM_nenPeriodicMode )
      {
         SWTIM__vPlaceTimer( timer );
      }

      timer->handler( timer );
   }

   if( SWTIM__stTimerHead != NULL )
   {
      SWTIM__stTimerHead->timeout -= u16Elapsed;
   }
   else
   {
      HWTIM_vStopTimer();
   }
}

static void SWTIM__vPlaceTimer( SWTIM_tstTimer *timer )
{
   if( SWTIM__stTimerHead != NULL )
   {
      SWTIM_tstTimer *t;
      SWTIM_tstTimer *prev = NULL;
      uint32 timeout = timer->interval;

      for( t = SWTIM__stTimerHead; t; t = t->next )
      {
         if( timeout < t->timeout )
         {
            t->timeout -= timeout;
            break;
         }
         else
         {
            timeout -= t->timeout;
         }

         prev = t;
      }

      timer->timeout = timeout;

      if( prev != NULL )
      {
         timer->next = prev->next;
         prev->next = timer;
      }
      else
      {
         timer->next = SWTIM__stTimerHead;
         SWTIM__stTimerHead = timer;
      }
   }
   else
   {
      timer->next = NULL;
      timer->timeout = timer->interval;
      SWTIM__stTimerHead = timer;
   }
}

void SWTIM_vReset( void )
{
   SWTIM__stTimerHead = NULL;
}

void SWTIM_vTimerStart( SWTIM_tstTimer *timer )
{
   if( SWTIM_boTimerStarted( timer ) == False )
   {
      /* if a hardware timer is not already running */
      if( HWTIM_boIsTimerRunning() == False )
      {
         /* start it */
         HWTIM_vStartTimer();
      }

      SWTIM__vPlaceTimer( timer );
   }
}

void SWTIM_vTimerStop( SWTIM_tstTimer *timer )
{
   SWTIM_tstTimer *t;
   SWTIM_tstTimer *prev = NULL;

   for( t = SWTIM__stTimerHead; t; t = t->next )
   {
      if( t == timer )
      {
         if( prev != NULL )
         {
            prev->next = t->next;
         }
         else
         {
            SWTIM__stTimerHead = t->next;
         }

         if( t->next )
         {
            t->next->timeout += timer->timeout;
         }

         break;
      }

      prev = t;

   }
}

bool SWTIM_boTimerStarted( SWTIM_tstTimer *timer )
{
   SWTIM_tstTimer *t;
   bool boRetVal = False;

   for( t = SWTIM__stTimerHead; t; t = t->next )
   {
      if( t == timer )
      {
         boRetVal = True;
      }
   }

   return boRetVal;
}

/* Hook into the hardware timer interrupt tick */
bool SWTIM_boUpdateTimer( void )
{
   SWTIM__vUpdateTimer();
   return True;
}
